﻿namespace Beetle
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Text;

    public class BufferReader : IDisposable
    {
        private const int _field_a = -2147483648;
        private const long _field_b = -9223372036854775808L;
        internal IList<Class_b> _field_c;
        private int _field_d;
        private Class_b _field_e;
        private int _field_f;
        private IByteConverter _field_g;
        private Class_b _field_h;
        [ThreadStatic]
        private static Class_aj _field_i;
        private int _field_j;
        private ByteArraySegment _field_k;
        private ByteArraySegment _field_l;
        private bool _field_m;
        public Encoding Coding;
        public bool EnabledVariant;

        public BufferReader()
        {
            this._field_c = new List<Class_b>(8);
            this._field_g = TcpUtils.ByteConverters.Pop();
            this._field_k = new ByteArraySegment();
            this.Coding = Encoding.UTF8;
        }

        public BufferReader(Encoding coding)
        {
            this._field_c = new List<Class_b>(8);
            this._field_g = TcpUtils.ByteConverters.Pop();
            this._field_k = new ByteArraySegment();
            this.Coding = coding;
        }

        public BufferReader(Encoding coding, BufferWriter write)
        {
            this._field_c = new List<Class_b>(8);
            this._field_g = TcpUtils.ByteConverters.Pop();
            this._field_k = new ByteArraySegment();
            this.Coding = coding;
            while (write._field_b.Count > 0)
            {
                this._field_h = write._field_b.Dequeue();
                this._field_h.c();
                this._field_f += this._field_h._field_h;
                this._field_c.Add(this._field_h);
            }
            this.c();
        }

        internal BufferReader(Encoding A_0, IList<Class_b> A_1)
        {
            this._field_c = new List<Class_b>(8);
            this._field_g = TcpUtils.ByteConverters.Pop();
            this._field_k = new ByteArraySegment();
            this._field_c = A_1;
            this.Coding = A_0;
            for (int i = 0; i < A_1.Count; i++)
            {
                this._field_f += A_1[i]._field_h;
                A_1[i].c();
            }
            this.c();
        }

        private ulong a()
        {
            ulong data = this.Read(1).GetData(0);
            if ((data & ((ulong)0x80L)) != 0L)
            {
                data &= (ulong)0x7fL;
                ulong num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 7;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 14;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 0x15;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 0x1c;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 0x23;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 0x2a;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 0x31;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (num2 & 0x7fL) << 0x38;
                if ((num2 & ((ulong)0x80L)) == 0L)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= num2 << 0x3f;
                if ((num2 & 18446744073709551614L) != 0L)
                {
                    throw new OverflowException("ReadUInt64Variant Error!");
                }
            }
            return data;
        }

        private int a(uint A_0)
        {
            int num = (int)A_0;
            return (-(num & 1) ^ ((num >> 1) & 0x7fffffff));
        }

        private long a(ulong A_0)
        {
            long num = (long)A_0;
            return (-(num & 1L) ^ ((num >> 1) & 0x7fffffffffffffffL));
        }

        private uint b()
        {
            uint data = this.Read(1).GetData(0);
            if ((data & 0x80) != 0)
            {
                data &= 0x7f;
                uint num2 = this.Read(1).GetData(0);
                data |= (uint)((num2 & 0x7f) << 7);
                if ((num2 & 0x80) == 0)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (uint)((num2 & 0x7f) << 14);
                if ((num2 & 0x80) == 0)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= (uint)((num2 & 0x7f) << 0x15);
                if ((num2 & 0x80) == 0)
                {
                    return data;
                }
                num2 = this.Read(1).GetData(0);
                data |= num2 << 0x1c;
                if ((num2 & 240) != 0)
                {
                    throw new OverflowException("ReadUInt32Variant Error!");
                }
            }
            return data;
        }

        private void c()
        {
            this._field_e = this._field_c[this._field_d];
            this._field_d++;
        }

        public void CleanBuffer()
        {
            for (int i = 0; i < this._field_c.Count; i++)
            {
                this._field_c[i].Dispose();
            }
            this._field_c.Clear();
        }

        private T[] createArray<T>()
        {
            return new T[this.ReadInt32()];
        }

        private IList<T> createList<T>(out int count)
        {
            count = this.ReadInt32();
            return new List<T>(count);
        }

        private static Class_aj d()
        {
            if (_field_i == null)
            {
                _field_i = new Class_aj();
            }
            return _field_i;
        }

        public void Dispose()
        {
            lock (this)
            {
                if (!this._field_m)
                {
                    for (int i = 0; i < this._field_c.Count; i++)
                    {
                        this._field_c[i].Dispose();
                    }
                    if (this._field_g != null)
                    {
                        TcpUtils.ByteConverters.Push(this._field_g);
                    }
                    this._field_c.Clear();
                    this._field_k.Clear();
                    this._field_m = true;
                }
            }
        }

        public void Import(BufferWriter write)
        {
            this._field_d = 0;
            this._field_f = 0;
            while (write._field_b.Count > 0)
            {
                this._field_h = write._field_b.Dequeue();
                this._field_h.c();
                this._field_f += this._field_h._field_h;
                this._field_c.Add(this._field_h);
            }
            this.c();
        }

        public void Import(ByteArraySegment segment)
        {
            this._field_d = 0;
            this._field_f = 0;
            Class_b item = new Class_b();
            item.a(segment);
            this._field_c.Add(item);
            this.c();
        }

        public ByteArraySegment Read(int count)
        {
            this._field_l = this._field_e.d(count);
            if (this._field_l.Count == count)
            {
                return this._field_l;
            }
            this._field_j = 0;
            byte[] dst = new byte[count];
            while (true)
            {
                Buffer.BlockCopy(this._field_l._field_a, this._field_l.Offset, dst, this._field_j, this._field_l.Count);
                this._field_j += this._field_l.Count;
                if (this._field_j >= count)
                {
                    break;
                }
                this.c();
                this._field_l = this._field_e.d(count - this._field_j);
            }
            this._field_k.SetInfo(dst, 0, count);
            return this._field_k;
        }

        public void Read(int count, ByteArraySegment bas)
        {
            if ((count > bas.BufferLength) || (bas.Array == null))
            {
                throw NetTcpException.ReadToByteArraySegment();
            }
            this._field_l = this._field_e.d(count);
            if (this._field_l.Count == count)
            {
                Buffer.BlockCopy(this._field_l._field_a, this._field_l.Offset, bas._field_a, 0, this._field_l.Count);
                bas.SetInfo(0, count);
            }
            else
            {
                this._field_j = 0;
                while (true)
                {
                    Buffer.BlockCopy(this._field_l._field_a, this._field_l.Offset, bas._field_a, this._field_j, this._field_l.Count);
                    this._field_j += this._field_l.Count;
                    if (this._field_j >= count)
                    {
                        break;
                    }
                    this.c();
                    this._field_l = this._field_e.d(count - this._field_j);
                }
                bas.SetInfo(0, count);
            }
        }

        public int Read32Variant()
        {
            return this.a(this.b());
        }

        public long Read64Variant()
        {
            return this.a(this.a());
        }

        public bool ReadBool()
        {
            return this._field_g.ReadBool(this);
        }

        public IList<bool> ReadBoolList()
        {
            int num;
            IList<bool> list = this.createList<bool>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadBool());
            }
            return list;
        }

        public bool[] ReadBools()
        {
            bool[] flagArray = this.createArray<bool>();
            for (int i = 0; i < flagArray.Length; i++)
            {
                flagArray[i] = this.ReadBool();
            }
            return flagArray;
        }

        public byte ReadByte()
        {
            return this._field_g.ReadByte(this);
        }

        public byte[] ReadByteArray()
        {
            int count = this.ReadInt32();
            if (count > 0)
            {
                return this.ReadBytes(count);
            }
            return new byte[0];
        }

        public void ReadByteArray(ByteArraySegment bas)
        {
            int count = this.ReadInt32();
            this.Read(count, bas);
        }

        public byte[] ReadBytes(int count)
        {
            ByteArraySegment segment = this.Read(count);
            if ((segment.Offset == 0) && (segment.Count == segment.Array.Length))
            {
                return segment.Array;
            }
            byte[] dst = new byte[count];
            Buffer.BlockCopy(segment._field_a, segment.Offset, dst, 0, segment.Count);
            return dst;
        }

        public char ReadChar()
        {
            return (char)((ushort)this.ReadInt16());
        }

        public IList<char> ReadCharList()
        {
            int num;
            IList<char> list = this.createList<char>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadChar());
            }
            return list;
        }

        public char[] ReadChars()
        {
            char[] chArray = this.createArray<char>();
            for (int i = 0; i < chArray.Length; i++)
            {
                chArray[i] = this.ReadChar();
            }
            return chArray;
        }

        public DateTime ReadDate()
        {
            return new DateTime(this.ReadInt64());
        }

        public DateTime[] ReadDates()
        {
            DateTime[] timeArray = this.createArray<DateTime>();
            for (int i = 0; i < timeArray.Length; i++)
            {
                timeArray[i] = this.ReadDate();
            }
            return timeArray;
        }

        public IList<DateTime> ReadDateTimeList()
        {
            int count = 0;
            IList<DateTime> list = this.createList<DateTime>(out count);
            for (int i = 0; i < count; i++)
            {
                list.Add(this.ReadDate());
            }
            return list;
        }

        public unsafe double ReadDouble()
        {
            if (this.EnabledVariant)
            {
                var v = this.Read64Variant();

                return *(((double*)&v));

            }
            var v2 = this.ReadInt64();
            return *(((double*)&v2));
        }

        public IList<double> ReadDoubleList()
        {
            int count = 0;
            IList<double> list = this.createList<double>(out count);
            for (int i = 0; i < count; i++)
            {
                list.Add(this.ReadDouble());
            }
            return list;
        }

        public double[] ReadDoubles()
        {
            double[] numArray = this.createArray<double>();
            for (int i = 0; i < numArray.Length; i++)
            {
                numArray[i] = this.ReadDouble();
            }
            return numArray;
        }

        public unsafe double ReadDoubleVariant()
        {
            var v = this.Read64Variant();

            return *(((double*)&v));
        }

        public unsafe float ReadFloat()
        {
            if (this.EnabledVariant)
            {
                var v1 = this.Read32Variant();
                return *(((float*)&v1));
            }
            var v2 = this.ReadInt32();
            return *(((float*)&v2));
        }

        public IList<float> ReadFloatList()
        {
            int num;
            IList<float> list = this.createList<float>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadFloat());
            }
            return list;
        }

        public float[] ReadFloats()
        {
            float[] numArray = this.createArray<float>();
            for (int i = 0; i < numArray.Length; i++)
            {
                numArray[i] = this.ReadFloat();
            }
            return numArray;
        }

        public unsafe float ReadFloatVariant()
        {
            var v = this.Read32Variant();
            return *(((float*)&v));
        }

        public unsafe short ReadInt16()
        {
            if (this._field_e.a(2))
            {
                short num;
                fixed (byte* numRef = &(this._field_e._field_e[this._field_e._field_g]))
                {
                    num = *((short*)numRef);
                }
                this._field_e._field_g += 2;
                return num;
            }
            return this._field_g.ReadInt16(this);
        }

        public IList<short> ReadInt16List()
        {
            int num;
            IList<short> list = this.createList<short>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadInt16());
            }
            return list;
        }

        public short[] ReadInt16s()
        {
            short[] numArray = this.createArray<short>();
            for (int i = 0; i < numArray.Length; i++)
            {
                numArray[i] = this.ReadInt16();
            }
            return numArray;
        }

        public unsafe int ReadInt32()
        {
            if (this.EnabledVariant)
            {
                return this.Read32Variant();
            }
            if (this._field_e.a(4))
            {
                int num;
                fixed (byte* numRef = &(this._field_e._field_e[this._field_e._field_g]))
                {
                    num = *((int*)numRef);
                }
                this._field_e._field_g += 4;
                return num;
            }
            return this._field_g.ReadInt32(this);
        }

        public IList<int> ReadInt32List()
        {
            int num;
            IList<int> list = this.createList<int>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadInt32());
            }
            return list;
        }

        public int[] ReadInt32s()
        {
            int[] numArray = this.createArray<int>();
            for (int i = 0; i < numArray.Length; i++)
            {
                numArray[i] = this.ReadInt32();
            }
            return numArray;
        }

        public unsafe long ReadInt64()
        {
            if (this.EnabledVariant)
            {
                return this.Read64Variant();
            }
            if (this._field_e.a(8))
            {
                long num;
                fixed (byte* numRef = &(this._field_e._field_e[this._field_e._field_g]))
                {
                    num = *((long*)numRef);
                }
                this._field_e._field_g += 8;
                return num;
            }
            return this._field_g.ReadInt64(this);
        }

        public IList<long> ReadInt64List()
        {
            int num;
            IList<long> list = this.createList<long>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadInt64());
            }
            return list;
        }

        public long[] ReadInt64s()
        {
            long[] numArray = this.createArray<long>();
            for (int i = 0; i < numArray.Length; i++)
            {
                numArray[i] = this.ReadInt64();
            }
            return numArray;
        }

        public T ReadObject<T>() where T : IMessage, new()
        {
            T local = (default(T) == null) ? Activator.CreateInstance<T>() : default(T);
            local.Load(this);
            return local;
        }

        public T ReadObject<T>(MessagePool<T> pool) where T : IMessage, IObjectReset, new()
        {
            T local = pool.Pop();
            local.Load(this);
            return local;
        }

        public IList<T> ReadObjects<T>() where T : IMessage, new()
        {
            int capacity = this.ReadInt32();
            List<T> list = new List<T>(capacity);
            for (int i = 0; i < capacity; i++)
            {
                list.Add(this.ReadObject<T>());
            }
            return list;
        }

        public IList<T> ReadObjects<T>(MessagePool<T> pool) where T : IMessage, IObjectReset, new()
        {
            int capacity = this.ReadInt32();
            List<T> list = new List<T>(capacity);
            for (int i = 0; i < capacity; i++)
            {
                list.Add(this.ReadObject<T>(pool));
            }
            return list;
        }

        public string ReadShortString()
        {
            ushort count = this.ReadUInt16();
            if (count > TcpUtils.DataPacketMaxLength)
            {
                NetTcpException.DataOverflow();
            }
            if (count > 0)
            {
                return this.ReadString(count);
            }
            return null;
        }

        public string ReadString()
        {
            int num = this.ReadInt32();
            if (num > TcpUtils.DataPacketMaxLength)
            {
                NetTcpException.DataOverflow();
            }
            if (num <= 0)
            {
                return null;
            }
            if (this._field_e.a(num))
            {
                string str = this.Coding.GetString(this._field_e._field_e, this._field_e._field_g, num);
                this._field_e._field_g += num;
                return str;
            }
            ByteArraySegment segment = this.Read(num);
            return this.Coding.GetString(segment._field_a, segment.Offset, segment.Count);
        }

        public string ReadString(int count)
        {
            if (this._field_e.a(count))
            {
                string str = this.Coding.GetString(this._field_e._field_e, this._field_e._field_g, count);
                this._field_e._field_g += count;
                return str;
            }
            ByteArraySegment segment = this.Read(count);
            return this.Coding.GetString(segment._field_a, segment.Offset, segment.Count);
        }

        public IList<string> ReadStringList()
        {
            int num;
            IList<string> list = this.createList<string>(out num);
            for (int i = 0; i < num; i++)
            {
                list.Add(this.ReadString());
            }
            return list;
        }

        public string[] ReadStrings()
        {
            string[] strArray = this.createArray<string>();
            for (int i = 0; i < strArray.Length; i++)
            {
                strArray[i] = this.ReadString();
            }
            return strArray;
        }

        public uint ReadU32Variant()
        {
            return this.b();
        }

        public ulong ReadU64Variant()
        {
            return this.a();
        }

        public unsafe ushort ReadUInt16()
        {
            if (this._field_e.a(2))
            {
                ushort num;
                fixed (byte* numRef = &(this._field_e._field_e[this._field_e._field_g]))
                {
                    num = *((ushort*)numRef);
                }
                this._field_e._field_g += 2;
                return num;
            }
            return this._field_g.ReadUInt16(this);
        }

        public unsafe uint ReadUInt32()
        {
            if (this.EnabledVariant)
            {
                return this.ReadU32Variant();
            }
            if (this._field_e.a(4))
            {
                uint num;
                fixed (byte* numRef = &(this._field_e._field_e[this._field_e._field_g]))
                {
                    num = *((uint*)numRef);
                }
                this._field_e._field_g += 4;
                return num;
            }
            return this._field_g.ReadUInt32(this);
        }

        public unsafe ulong ReadUInt64()
        {
            if (this.EnabledVariant)
            {
                return this.ReadU64Variant();
            }
            if (this._field_e.a(8))
            {
                ulong num;
                fixed (byte* numRef = &(this._field_e._field_e[this._field_e._field_g]))
                {
                    num = *((ulong*)numRef);
                }
                this._field_e._field_g += 8;
                return num;
            }
            return this._field_g.ReadUInt64(this);
        }

        public byte[] ToBytes()
        {
            byte[] destinationArray = new byte[this.Count];
            int destinationIndex = 0;
            for (int i = 0; i < this._field_c.Count; i++)
            {
                Class_b _b = this._field_c[i];
                Array.Copy(_b._field_e, 0, destinationArray, destinationIndex, _b._field_h);
                destinationIndex += _b._field_h;
            }
            return destinationArray;
        }

        public int Count
        {
            get
            {
                return this._field_f;
            }
        }
    }
}

